package com.qunar.toku.proxy;

import static org.jboss.netty.channel.Channels.pipeline;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.serialization.ClassResolvers;
import org.jboss.netty.handler.codec.serialization.ObjectDecoder;
import org.jboss.netty.handler.codec.serialization.ObjectEncoder;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;

import com.qunar.toku.TokuConst;
import com.qunar.toku.handler.ChannelServerHandler;
import com.qunar.toku.handler.ServerHandler;

public final class ServerProxy {
	private final InternalLogger logger =
	        InternalLoggerFactory.getInstance(ServerProxy.class);
	private final ChannelServerHandler handler;
	
	public static void bind(int port) {
		new ServerProxy(ServerHandler.class).bindInternal(port);
	}
	
	private ServerProxy(Class clazz) {
		try {
			handler = (ChannelServerHandler) clazz.newInstance();
		} catch (Exception e) {
			throw new InstantiationError(e.getMessage());
		}
	}

	private void bindInternal(int port) {
		ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(),
				Executors.newCachedThreadPool()));
		bootstrap.setPipelineFactory(new ChannelPipelineFactory() {

			@Override
			public ChannelPipeline getPipeline() {
				ChannelPipeline pipeline = pipeline();
				//默认最大传输帧大小为16M
				pipeline.addLast("encode", new ObjectEncoder(TokuConst.DEFAULT_MAX_PAKAGE_SIZE));
				pipeline.addLast("decode", new ObjectDecoder(TokuConst.DEFAULT_MAX_PAKAGE_SIZE, ClassResolvers.weakCachingConcurrentResolver(null)));
				pipeline.addLast("handler", handler);
				return pipeline;
			}

		});
		bootstrap.setOption("child.receiveBufferSize", TokuConst.DEFAULT_RECV_BUFFER_SIZE);
		bootstrap.setOption("child.sendBufferSize", TokuConst.DEFAULT_SEND_BUFFER_SIZE);
		bootstrap.setOption("child.tcpNoDelay", true); //关闭Nagle算法
		/*
		 * tcp定期发送心跳包,检测连接是否端看,系统处理,程序需要处理坏连接(有tcp长连接下才有意义)
		 * ping走的是icmp协议,只能知道机器通不通,客户端链接是否断开不知道
		 * 所以想要知道客户端连接是否断开或下线,要通过链接的 keep_alive
		 *
		 */
		bootstrap.setOption("child.keepAlive", true);
		bootstrap.setOption("reuseAddress", true);
		bootstrap.bind(new InetSocketAddress(port));
		logger.info("Listener on server port:" + port);
	}

}
